package com.ak.cluster;

import java.util.Collections;
import java.util.List;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.utils.Array;

public abstract class GameObject implements Comparable<GameObject>{
	
	
	
	public enum RenderOptions{
		SOLID(0),
		ALPHA(1);
		public int code;
		private RenderOptions(int rCode)
		{
			code = rCode;
		}
		
	}
	
	public enum PhysicsBodyOptions{
		STATIC(0), 
		DYNAMIC(1),
		KINEMATIC(2),
		NONE(3);
		
		public int code;
		private PhysicsBodyOptions(int rCode){
			code = rCode;
		}
	}
	
	public int density = 10;
	
	//Used to track the object
	protected static int instanceCount;	
		
	public static Mesh lastMesh = null;
	
	public static Texture lastTexture = null;
	
	public int chosenRenderSetting;
	
	public int chosenBodyType;
	
	public Body objectBody;
	
	//Needs to be assigned UNIQUE ONLY
	protected int textureID;
	
	protected int objectID;
	
	public Mesh assetMesh;
	
	public Texture assetTexture; 
	
	public Vector2 position;
	
	public Vector2 scale;
	
	public Socket[] attachedSockets;
	
	public GameObject[] objectSockets;
	
	public GameObject[] attachedObjects;
	

	protected GameObject()
	{
		instanceCount++;
		position = new Vector2();
		scale    = new Vector2();
		position.x = 0;
		position.y = 0;
		textureID = 0;
		objectID  = instanceCount;
		chosenRenderSetting = -1;			
		
		assetMesh = new Mesh(true,4,0,
				  new VertexAttribute(Usage.Position,3,"a_position"),
				  new VertexAttribute(Usage.TextureCoordinates,2,"a_textureCoords"));
		
		// attachedSockets = 
		// objectSockets = 
		// attachedObjects = 
		

	}
	
	
	/**
	 * Used to ensure that the GameObject has a texture. 
	 * @return Ternary true or false
	 */
	public boolean hasTexture(){ return assetTexture!=null&&textureID!=0 ? true:false; }

	public Texture assignTexture(String texturePath)
	{
		return assetTexture = new Texture(Gdx.files.internal(texturePath));
	}
	

	public Mesh buildMesh(Mesh IN_Mesh,Texture IN_Texture)
	{
		IN_Mesh.setAutoBind(false);
		if(lastMesh == IN_Mesh)
			this.assetMesh = lastMesh;
		else
		{
			
			IN_Mesh.setVertices(new float[]{-1*(IN_Texture.getWidth()*0.05f),-1*(IN_Texture.getHeight()*0.05f),0,0,1,  //Bottom Left
											   (IN_Texture.getWidth()*0.05f),-1*(IN_Texture.getHeight()*0.05f),0,1,1,  //Bottom Right
											   (IN_Texture.getWidth()*0.05f),   (IN_Texture.getHeight()*0.05f),0,1,0,  //Top Right
											-1*(IN_Texture.getWidth()*0.05f),   (IN_Texture.getHeight()*0.05f),0,0,0});//Top Left
			this.assetMesh = IN_Mesh;
			lastMesh = IN_Mesh;
		}
		return this.assetMesh;
		
	}
	
	/*
	 * Used to compare the TEXTURE_ID's of two different GameObjects. 
	 * This must be implemented before using Collections.sort(*LIST*);
	 * This also must be overridden when implementing  Comparable
	 * (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(GameObject other)
	{
		if(this.textureID > other.textureID)
		{
			return 1;
		}
		if(this.textureID < other.textureID)
		{
			return -1;
		}
		return 0;
	}
	
	//Sorts by texture id to speed up the render process.
	protected List<GameObject> optimizeList(List<GameObject> mList)
	{
		Collections.sort(mList);
		return mList;
	}
	

	
	protected abstract void dispose();
	
	protected abstract void update();

	
	
}
